/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
 * MA  02110-1301, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */

package com.aionemu.gameserver.model.gameobjects.stats;

import java.util.List;

import com.aionemu.gameserver.dataholders.DataManager;
import com.aionemu.gameserver.model.EmotionType;
import com.aionemu.gameserver.model.gameobjects.Item;
import com.aionemu.gameserver.model.gameobjects.player.Equipment;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.state.CreatureState;
import com.aionemu.gameserver.model.gameobjects.stats.modifiers.StatModifier;
import com.aionemu.gameserver.model.templates.stats.PlayerStatsTemplate;
import com.aionemu.gameserver.network.aion.serverpackets.SM_EMOTION;
import com.aionemu.gameserver.skillengine.model.IStatEffect;
import com.aionemu.gameserver.utils.PacketSendUtility;

/**
 * @author Mr.Poke
 * 
 */
public class PlayerGameStats extends CreatureGameStats<Player>
{

	private int speed = 0;
	private int attackSpeed = 0;
	private boolean needEmote = false;
	/**
	 * 
	 * @param owner
	 */
	public PlayerGameStats(Player owner)
	{
		super(owner);
	}

	public void sendStatUpdateEmote()
	{
		if (needEmote)
		{
			needEmote = false;
			PacketSendUtility.broadcastPacket(owner, new SM_EMOTION(owner, EmotionType.START_EMOTE2, 0, 0), true);
		}
	}
	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#addModifiers(com.aionemu.gameserver.skillengine.model.IStatEffect, java.util.TreeSet)
	 */
	@Override
	public boolean addModifiers(IStatEffect effectOwner, List<StatModifier> modifiers)
	{
		if (super.addModifiers(effectOwner, modifiers))
		{
			owner.updatePlayerStat();
			return true;
		}
		return false;
	}
	
	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#endEffect(com.aionemu.gameserver.skillengine.model.IStatEffect)
	 */
	@Override
	public boolean endEffect(IStatEffect id)
	{
		if (super.endEffect(id))
		{
			owner.updatePlayerStat();
			return true;
		}
		return false;
	}
	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getMovementSpeed()
	 */
	@Override
	public Stat getMovementSpeed()
	{
		Stat movementSpeed;
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		if (owner.isInState(CreatureState.FLYING) || owner.isInState(CreatureState.GLIDING))
			movementSpeed = getStat(StatEnum.FLY_SPEED, Math.round(pst.getFlySpeed()*1000));
		else if (owner.isInState(CreatureState.FLIGHT_TELEPORT))
			movementSpeed = getStat(StatEnum.SPEED, 12000);
		else if (owner.isInState(CreatureState.WALKING))
			movementSpeed = getStat(StatEnum.SPEED, Math.round(pst.getWalkSpeed()*1000));
		else 
			movementSpeed =getStat(StatEnum.SPEED, Math.round(pst.getRunSpeed()*1000));
		if (movementSpeed.getCurrent() != speed)
		{
			speed = movementSpeed.getCurrentInt();
			needEmote = true;
		}
		return movementSpeed;
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getMaxHP()
	 */
	@Override
	public Stat getMaxHP()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		return getStat(StatEnum.MAXHP, pst.getMaxHp());
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getMaxMP()
	 */
	@Override
	public Stat getMaxMP()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		return getStat(StatEnum.MAXMP, pst.getMaxMp());
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getAttackSpeed()
	 */
	@Override
	public Stat getAttackSpeed()
	{
		int base = 1500;
		Equipment equipment = owner.getEquipment();
		Item mainHandWeapon = equipment.getMainHandWeapon();
		
		if (mainHandWeapon != null)
		{
			base = mainHandWeapon.getItemTemplate().getWeaponStats().getAttackSpeed();
			Item offWeapon = owner.getEquipment().getOffHandWeapon();
			if (offWeapon != null)
				base += offWeapon.getItemTemplate().getWeaponStats().getAttackSpeed() / 4;
		}
		Stat aSpeed = getStat(StatEnum.ATTACK_SPEED, base);
		if (attackSpeed != aSpeed.getCurrent())
		{
			attackSpeed = aSpeed.getCurrentInt();
			needEmote = true;
		}
		return aSpeed;
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getAttackRange()
	 */
	@Override
	public Stat getAttackRange()
	{
		int base = 1500;
		Equipment equipment = owner.getEquipment();
		Item mainHandWeapon = equipment.getMainHandWeapon();
		if (mainHandWeapon != null)
		{
			base = mainHandWeapon.getItemTemplate().getWeaponStats().getAttackRange();
		}
		return getStat(StatEnum.ATTACK_RANGE, base);
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getPDef()
	 */
	@Override
	public Stat getPDef()
	{
		return getStat(StatEnum.PHYSICAL_DEFENSE, 0);
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getMagicalResist()
	 */
	@Override
	public Stat getMagicalResist()
	{
		return getStat(StatEnum.MAGICAL_RESIST, 0);
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getPower()
	 */
	@Override
	public Stat getPower()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		return getStat(StatEnum.POWER, pst.getPower());
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getHealth()
	 */
	@Override
	public Stat getHealth()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		return getStat(StatEnum.HEALTH, pst.getHealth());
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getAccuracy()
	 */
	@Override
	public Stat getAccuracy()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		return getStat(StatEnum.ACCURACY, pst.getAccuracy());
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getAgility()
	 */
	@Override
	public Stat getAgility()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		return getStat(StatEnum.AGILITY, pst.getAgility());
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getKnowledge()
	 */
	@Override
	public Stat getKnowledge()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		return getStat(StatEnum.KNOWLEDGE, pst.getKnowledge());
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getWill()
	 */
	@Override
	public Stat getWill()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		return getStat(StatEnum.WILL, pst.getWill());
	}

	public Stat getMainHandPAttack()
	{
		int base = 18;
		Equipment equipment = owner.getEquipment();
		Item mainHandWeapon = equipment.getMainHandWeapon();
		if (mainHandWeapon != null)
		{
			if (mainHandWeapon.getItemTemplate().getAttackType().isMagic())
				return new Stat();
			int min = mainHandWeapon.getItemTemplate().getWeaponStats().getMinDamage();
			int max = mainHandWeapon.getItemTemplate().getWeaponStats().getMaxDamage();
			base = (min+max)/2;
		}
		Stat stat = getStat(StatEnum.PHYSICAL_ATTACK, base);
		return getStat(StatEnum.PHYSICAL_ATTACK_MAIN_HAND, stat);
	}
	
	public Stat getMainHandMAttack()
	{
		int base = 0;
		Equipment equipment = owner.getEquipment();
		Item mainHandWeapon = equipment.getMainHandWeapon();
		if (mainHandWeapon != null)
		{
			if (!mainHandWeapon.getItemTemplate().getAttackType().isMagic())
				return new Stat();
			int min = mainHandWeapon.getItemTemplate().getWeaponStats().getMinDamage();
			int max = mainHandWeapon.getItemTemplate().getWeaponStats().getMaxDamage();
			base = (min+max)/2;
		}
		return getStat(StatEnum.MAGICAL_ATTACK, base);
	}
	
	public Stat getOffHandPAttack()
	{
		Equipment equipment = owner.getEquipment();
		Item offHandWeapon = equipment.getOffHandWeapon();
		if (offHandWeapon != null)
		{
			int base = 0;
			int min = offHandWeapon.getItemTemplate().getWeaponStats().getMinDamage();
			int max = offHandWeapon.getItemTemplate().getWeaponStats().getMaxDamage();
			base = (min+max)/2;
			Stat stat = getStat(StatEnum.PHYSICAL_ATTACK, base);
			return getStat(StatEnum.PHYSICAL_ATTACK_OFF_HAND, stat);
		}
		return new Stat();
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getMainHandPCritical()
	 */
	@Override
	public Stat getMainHandPCritical()
	{
		int base = 2;
		Equipment equipment = owner.getEquipment();
		Item mainHandWeapon = equipment.getMainHandWeapon();
		if (mainHandWeapon != null)
		{
			base = mainHandWeapon.getItemTemplate().getWeaponStats().getPhysicalCritical();
		}
		Stat stat = getStat(StatEnum.PHYSICAL_CRITICAL, base);
		return getStat(StatEnum.PHYSICAL_CRITICAL_MAIN_HAND, stat);
	}
	
	public Stat getOffHandPCritical()
	{
		Equipment equipment = owner.getEquipment();
		Item offHandWeapon = equipment.getOffHandWeapon();
		if (offHandWeapon != null)
		{
			int base = 2;
			base = offHandWeapon.getItemTemplate().getWeaponStats().getPhysicalCritical();
			Stat stat = getStat(StatEnum.PHYSICAL_CRITICAL, base);
			return getStat(StatEnum.PHYSICAL_CRITICAL_OFF_HAND, stat);
		}
		return new Stat();
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getPAccuracy()
	 */
	@Override
	public Stat getMainHandPAccuracy()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		int base = pst.getMainHandAccuracy();
		Equipment equipment = owner.getEquipment();
		Item mainHandWeapon = equipment.getMainHandWeapon();
		if (mainHandWeapon != null)
		{
			base += mainHandWeapon.getItemTemplate().getWeaponStats().getPhysicalAccuracy();
		}
		Stat stat = getStat(StatEnum.PHYSICAL_ACCURACY, base);
		return getStat(StatEnum.PHYSICAL_ACCURACY_MAIN_HAND, stat);
	}
	
	public Stat getOffHandPAccuracy()
	{
		Equipment equipment = owner.getEquipment();
		Item offHandWeapon = equipment.getOffHandWeapon();
		if (offHandWeapon != null)
		{
			PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
			int base = pst.getMainHandAccuracy();
			base += offHandWeapon.getItemTemplate().getWeaponStats().getPhysicalAccuracy();
			Stat stat = getStat(StatEnum.PHYSICAL_ACCURACY, base);
			return getStat(StatEnum.PHYSICAL_ACCURACY_OFF_HAND, stat);
		}
		return new Stat();
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getMagicalBoost()
	 */
	@Override
	public Stat getMagicalBoost()
	{
		int base = 0; 
		Item mainHandWeapon = owner.getEquipment().getMainHandWeapon();
		if (mainHandWeapon != null)
		{
			base += mainHandWeapon.getItemTemplate().getWeaponStats().getBoostMagicalSkill();
		}
		return getStat(StatEnum.BOOST_MAGICAL_SKILL, base);
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getMagicalAccuracy()
	 */
	@Override
	public Stat getMagicalAccuracy()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		int base = pst.getMagicAccuracy();
		Item mainHandWeapon = owner.getEquipment().getMainHandWeapon();
		if (mainHandWeapon != null)
		{
			base += mainHandWeapon.getItemTemplate().getWeaponStats().getMagicalAccuracy();
		}
		return getStat(StatEnum.MAGICAL_ACCURACY, base);
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getMagicalCritical()
	 */
	@Override
	public Stat getMagicalCritical()
	{
		return getStat(StatEnum.MAGICAL_CRITICAL, 50);
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getMagicalEvasion()
	 */
	@Override
	public Stat getEvasion()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		return getStat(StatEnum.EVASION, pst.getEvasion());
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getMagicalParry()
	 */
	@Override
	public Stat getParry()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		int base = pst.getParry();
		Item mainHandWeapon = owner.getEquipment().getMainHandWeapon();
		if (mainHandWeapon != null)
		{
			base += mainHandWeapon.getItemTemplate().getWeaponStats().getParry();
		}
		return getStat(StatEnum.PARRY, base);
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.gameobjects.stats.CreatureGameStats#getMagicalBlock()
	 */
	@Override
	public Stat getBlock()
	{
		PlayerStatsTemplate pst = DataManager.PLAYER_STATS_DATA.getTemplate(owner.getObjectTemplate().getPlayerClass(), owner.getLevel());
		return getStat(StatEnum.BLOCK, pst.getBlock());
	}
}
